
//-----------------MATRICES---------------
float4x4 xWorld: World;				
float4x4 xView: View;
float4x4 xProjection: Projection;
float4x4 xRotationMatrix;
float4x4 xReflectedView;

//######
//macierze odwrotne widoku i projekcji
float4x4 xInvView;
float4x4 xInvProj;
float4x4 xWorldView;
//######


//-----------------TEXTURES---------------

Texture xTexture;
sampler ColoredTextureSampler = sampler_state { texture = <xTexture> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};

Texture xDirtTexture;
sampler DirtTextureSampler = sampler_state { texture = <xDirtTexture> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};

Texture xGrassTexture;
sampler GrassTextureSampler = sampler_state { texture = <xGrassTexture> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};

Texture xRockTexture;
sampler RockTextureSampler = sampler_state { texture = <xRockTexture> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};

Texture xSnowTexture;
sampler SnowTextureSampler = sampler_state { texture = <xSnowTexture> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};


Texture xRefractionMap;
sampler RefractionMapSampler = sampler_state { texture = <xRefractionMap> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};

Texture xReflectionMap;
sampler ReflectionMapSampler = sampler_state { texture = <xReflectionMap> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};

Texture xWaterBumpMap;
sampler WaterBumpMapSampler = sampler_state { texture = <xWaterBumpMap> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};

Texture xRockBumpMap;
sampler RockBumpMapSampler = sampler_state { texture = <xRockBumpMap> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};



//######
Texture xColor; 
sampler ParticleColorSampler = sampler_state { texture = <xColor> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = Clamp; AddressV = Clamp;}; //Clamp

Texture xDiff; 
sampler3D ParticleDiffSampler = sampler_state { texture = <xDiff> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=POINT; AddressU = Wrap; AddressV = Wrap; AddressW = Clamp;};

Texture xSceneDepth; 
sampler SceneDepthSampler = sampler_state { texture = <xSceneDepth> ;
    magfilter = POINT; minfilter = POINT; mipfilter=POINT; AddressU = Clamp; AddressV = Clamp;};

textureCUBE xCubeShadowMap; 
samplerCUBE CubeShadowMapSampler = sampler_state
{
	Texture = <xCubeShadowMap>;
    MipFilter = NONE;
    MinFilter = NONE;
    MagFilter = NONE;
    AddressU = wrap;
    AddressV = wrap;
};

    
//######

//--------------- CONSTANTS ---------------

float xMaxHeight;
float xMinHeight;

bool xRefraction;
bool xReflection;

float xRockBumpHeight;


float4 xLightPosition;
float4 xAmbientLight;
float4 xCameraPosition;

float4 xWaterColor;
float xWaterLevel;


float xWindSpeed;
float xTime;


float xWaveLength;
float xWaveHeight;

//####
float3 xParticlePos; //przesuniecie particla o wektor (pozycja bezwzgledna)
float xParticleLife; //wiek particla - okresla kolor i klatke animacji spritea
float xParticleSize; //rozmiar
float xParticleFadeDistance; // dla odlegl 0-XPFD nastepuje efekt AlphaFadeIn, dla >odl Alpha=1
bool xSoftParticles; //gdy true to soft-particle

float4 xCubeLightPosition; //pozycja swiatla omni
float4 xEyePosition; //pozycja kamery
#define zOffset 0.5f 

const float4 materialAmbient = float4(0.9f, 0.9f, 0.9f, 1.0f);  
const float4 materialDiffuse = float4(1.0f, 1.0f, 1.0f, 1.0f);
const float4 materialSpecular = float4(1.0f, 1.0f, 1.0f, 1.0f);
const float4 globalAmbient = float4(1.0f, 1.0f, 1.0f, 1.0f);
const float4 lightDiffuse = float4(0.9f, 0.5f, 0.23f, 1.0f);
const float4 lightSpecular = float4(0.9f, 0.5f, 0.23f, 1.0f);
const float4 lightAttenuation = float4(0.0f, 0.05f, 0.0f, 1.0f);
const float specPower = 64.0f;
//####



//------------------- STRUCTS -------------------   


struct BufferToVertex
{
float3 Pos : POSITION;
float4 Normal : NORMAL;
float4 UV : TEXCOORD0;

};


struct VertexToPixel
{
float4 Pos:POSITION;
float4 Orig_Pos:TEXCOORD1;
float4 UV:TEXCOORD0;
float4 Normal: TEXCOORD2;
float4 TexWeights: TEXCOORD3;
float4 Pos3D:TEXCOORD4;
float4 Pos2D:TEXCOORD5;
};


struct PixelToFrame
{
float4 Color:COLOR;
float Depth:DEPTH;
};


struct WaterBufferToVertex
{
float3 Pos : POSITION;
float4 Normal : NORMAL;
float4 UV : TEXCOORD0;

};


struct WaterVertexToPixel
{
float4 Pos:POSITION;
float4 UV: TEXCOORD0;
float4 Normal: TEXCOORD2;
float4 ReflPos: TEXCOORD3;
float4 RefrPos: TEXCOORD4;
float4 Pos3D: TEXCOORD5;
float2 BumpPos: TEXCOORD6;
};

//####
struct VSParticleIn
{
    float3 Pos            : POSITION;
    float2 Tex            : TEXCOORD0;
};

struct PSParticleIn
{
    float4 Pos		  : POSITION;
    float2 Tex		  : TEXCOORD0;
    float2 ScreenTex	  : TEXCOORD1;
    float2 Depth	  : TEXCOORD2;
    float3 worldPos	  : TEXCOORD3;
    float3 particleOrig	  : TEXCOORD4;
    float3 particleColor  : TEXCOORD5;
};

struct PSCubeIn
{
    float4 oPositionLight : POSITION;
    float3 lightVec       : TEXCOORD0;
};

struct lightFuncOutput
{
    float4 diffuseResult;
    float4 specularResult;
};

struct PSCubeShadowMapIn
{
	float4 position  :  POSITION;
	float3 worldPos  :  TEXCOORD0;
	float3 normalW   :  TEXCOORD1;
	float3 cam2Vert  :  TEXCOORD2;
};

struct PSCubeShadowMapTexIn
{
float4 Pos:POSITION;
float4 Orig_Pos:TEXCOORD1;
float4 UV:TEXCOORD0;
float4 Normal: TEXCOORD2;
float4 TexWeights: TEXCOORD3;
float4 Pos3D:TEXCOORD4;
float4 Pos2D:TEXCOORD5;
float3 cam2Vert:TEXCOORD6;
};

//####


//---------------------- HELPER FUNCTIONS ------------------------
//######
lightFuncOutput LightPointSH(float3 inObjPos, 
						     float3 inNormal, 
						     float3 inCam2Vertex)
{
     lightFuncOutput output;
     output.diffuseResult = float4(0.0f, 0.0f, 0.0f, 1.0f);
     output.specularResult = float4(0.0f, 0.0f, 0.0f, 1.0f);

     float4 PLightDirection = 0.0f;
     PLightDirection.xyz = xCubeLightPosition.xyz - inObjPos;
     float distance = length(PLightDirection.xyz);
     PLightDirection.xyz = PLightDirection.xyz / distance;
    
     //compute attenuation factor
     PLightDirection.w = max(0, 1 / (lightAttenuation.x + 
     	                      		 lightAttenuation.y * distance + 
                               		 lightAttenuation.z * distance * distance) );
     
     //sample depth from cubic shadow map                         		 
	 float shadowMapDepth = texCUBE(CubeShadowMapSampler, float4(-(PLightDirection.xyz), 0.0f)).r;
	 //depth comparison
	 if(distance > shadowMapDepth)    
	 {
	 	 //the pixel is shadowed, so return zero for diffuse and specular
	 	 output.diffuseResult = float4(0.0f, 1.0f, 0.0f, 1.0f);
	 	 return output;
	 }     	
	 else
	 {
	 	 //the pixel is not in shadow, so compute diffuse and specular and return
	     float3 floatVecTmp = normalize(inCam2Vertex + PLightDirection.xyz);

         output.diffuseResult = PLightDirection.w * lightDiffuse * max(0, dot(inNormal, PLightDirection.xyz));
         output.specularResult = PLightDirection.w * lightSpecular * pow(max (0, dot(inNormal, floatVecTmp) ), specPower);
	 	 output.diffuseResult = float4(1.0f, 0.0f, 0.0f, 1.0f);
         return output;
	 }
//	 	 output.diffuseResult = float4(shadowMapDepth/10.0f, 0.0f, 0.0f, 1.0f);
//	 	 return output;
}

float LightPointSH2(float3 inObjPos, 
						     float3 inCam2Vertex)
{
     float4 PLightDirection = 0.0f;
     PLightDirection.xyz = xCubeLightPosition.xyz - inObjPos;
     float distance = length(PLightDirection.xyz);
     PLightDirection.xyz = PLightDirection.xyz / distance;
    
    
     //sample depth from cubic shadow map                         		 
	 float shadowMapDepth = texCUBE(CubeShadowMapSampler, float4(-(PLightDirection.xyz), 0.0f)).r;
	 //depth comparison
	 if(distance > shadowMapDepth)    
	 {
	 	 return 0.2f;
	 }     	
	 else
	 {
         return 1.0f;
	 }
}


//######



//---------------------- SHADERS ------------------------

//####
// ---- CUBE DEPTH --------------------------------

PSCubeIn cubedepthVS( float4 inPosition : POSITION )
{
    PSCubeIn output;

  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
    
    float4 positionW = mul( inPosition, xWorld );
    output.oPositionLight = mul( inPosition, WorldViewProj );
    
    output.lightVec = xCubeLightPosition.xyz - positionW.xyz; 

    return output;
}  

float4 cubedepthPS( PSCubeIn In ) : COLOR0
{
//    return length(In.lightVec) + zOffset;
    float3 Color=float3(1,1,1)*(length(In.lightVec) + zOffset);
	return float4(Color.xyz,1); 
    
    
} 


float4 cubedepthPSred( PSCubeIn In ) : COLOR0
{
    return float4(length(In.lightVec)/100 + zOffset,0,0,1);
}   

// ---- CUBE SHADOW MAPPING ----------------------

PSCubeShadowMapIn cubeshadowmappingVS(float4 inPosition  : POSITION,
                                float3 inNormal    : NORMAL)
                         
{
    PSCubeShadowMapIn output;

    float4x4 WorldViewProj;
    WorldViewProj=mul(xWorld,xView);
    WorldViewProj=mul(WorldViewProj,xProjection);

	float4 positionW = mul(inPosition, xWorld);

    output.cam2Vert = (xEyePosition - positionW).xyz; 
    output.position = mul(inPosition, WorldViewProj);
    output.worldPos = positionW.xyz;
    output.normalW = mul(inNormal, xWorld).xyz;
    
    return output;
}

float4 cubeshadowmappingPS(PSCubeShadowMapIn In) : COLOR0
{
    lightFuncOutput lightResult;
    
    float3 normal = normalize(In.normalW);
    float3 cam2Vert = normalize(In.cam2Vert);
    
    lightResult = LightPointSH(In.worldPos, normal, cam2Vert); //perform lighting/shadowing calculations
    
    float4 ambient = materialAmbient * globalAmbient;
    float4 diffuse = materialDiffuse * lightResult.diffuseResult;
    float4 specular = materialSpecular * lightResult.specularResult;

    float4 lightingColor = (ambient * (diffuse + specular));
    
    return lightingColor;
}
// ---- CUBE SHadow Mapping Textured

PSCubeShadowMapTexIn cubeshadowmappingtexVS(BufferToVertex IN)
{
  PSCubeShadowMapTexIn OUT = (PSCubeShadowMapTexIn)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0);
  OUT.Normal=IN.Normal;
  OUT.cam2Vert = (xEyePosition - OUT.Pos3D).xyz; 
	return OUT;
}

PixelToFrame cubeshadowmappingtexPS(PSCubeShadowMapTexIn IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;
float3 cam2Vert = normalize(IN.cam2Vert);
float lightResult = LightPointSH2(IN.Pos3D, cam2Vert);
float4 LightVector = normalize(xLightPosition - IN.Orig_Pos);
float LightIntensity = dot(LightVector,normalize(mul(IN.Normal,xRotationMatrix)));
if (xRefraction) if (IN.Pos3D.z>xWaterLevel) {OUT.Depth=1.0; LightIntensity=0.0f; xAmbientLight=float4(0,0,0,0);} 	
if (xReflection) if (IN.Pos3D.z<=xWaterLevel) {OUT.Depth=1.0; LightIntensity=0.0f; xAmbientLight=float4(0,0,0,0);} 	
OUT.Color = saturate(tex2D(ColoredTextureSampler, IN.UV)*LightIntensity*lightResult+xAmbientLight);
return OUT;
}




// ---- PARTICLE ---------

PSParticleIn particleVS(VSParticleIn IN)
{
  PSParticleIn OUT = (PSParticleIn)0;
  
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);

  float4 orig = mul( float4(IN.Pos.xyz,1), xWorld );
  OUT.particleOrig = orig.xyz;
    
  // calculate color from a 1d gradient texture
  OUT.particleColor=float3(0,0,0);
            
  float3 position = IN.Pos*xParticleSize;
  position = mul( position, xInvView ) + xParticlePos.xyz;
  OUT.Pos = mul( float4(position,1.0), WorldViewProj );
            
  // pass along the texcoords
  OUT.Tex = IN.Tex;
            
  // screenspace coordinates for the lookup into the depth buffer
  OUT.ScreenTex = OUT.Pos.xy/OUT.Pos.w;
            
  // output depth of this particle
  OUT.Depth = OUT.Pos.zw;
            
  // world position
  float4 posWorld = mul( float4(position,1.0), xWorld );
  OUT.worldPos = posWorld;							
            
  return OUT; 
}

float4 particlePS(PSParticleIn IN) : COLOR 
{
    float2 screenTex = 0.5*( IN.ScreenTex + float2(1,1));
    screenTex.y = 1 - screenTex.y;
  
    float4 particleSample = tex3D(ParticleDiffSampler, float3(IN.Tex.x,IN.Tex.y,saturate(xParticleLife)));
   
    float particleDepth = IN.Depth.x;
    particleDepth /= IN.Depth.y;

    float3 particleColor = tex2D(ParticleColorSampler, float2(xParticleLife,0.0f));
     
    float depthFade = 1;
     if( xSoftParticles )
    {
        float depthSample = tex2D(SceneDepthSampler, screenTex).r;

        float4 depthViewSample = mul( float4( IN.ScreenTex.xy, depthSample, 1 ), xInvProj );
        float4 depthViewParticle = mul( float4( IN.ScreenTex.xy, particleDepth, 1 ), xInvProj );
        
        float depthDiff = depthViewSample.z/depthViewSample.w - depthViewParticle.z/depthViewParticle.w;
        if( depthDiff < 0 ) depthDiff = 0.0f;
        depthFade = saturate( depthDiff / xParticleFadeDistance );
    }        
    float4 Light = xAmbientLight;
    particleSample.rgb *= particleColor; 
    particleSample.a *= depthFade;

    return particleSample;
}


//####

// ---- MULTITEXTURED --------

VertexToPixel multitexturedVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.UV=float4(IN.UV.xy,1.0,1.0);
  OUT.Normal=IN.Normal;
  float t=(IN.Pos.z-xMinHeight)/(xMaxHeight-xMinHeight);
  if (t<(1.0/7.0)) OUT.TexWeights=float4(1.0,0.0,0.0,0.0);
  if ((t>=(1.0/7.0)) && ((t<2.0/7.0))) OUT.TexWeights=float4(2.0-7.0*t,7.0*t-1,0.0,0.0);
  if ((t>=(2.0/7.0)) && ((t<3.0/7.0))) OUT.TexWeights=float4(0.0,1.0,0.0,0.0);
  if ((t>=(3.0/7.0)) && ((t<4.0/7.0))) OUT.TexWeights=float4(0.0,4.0-7.0*t,7.0*t-3,0.0);
  if ((t>=(4.0/7.0)) && ((t<5.0/7.0))) OUT.TexWeights=float4(0.0,0.0,1.0,0.0);
  if ((t>=(5.0/7.0)) && ((t<6.0/7.0))) OUT.TexWeights=float4(0.0,0.0,6.0-7.0*t,7.0*t-5.0);
  if (t>=(6.0/7.0)) OUT.TexWeights=float4(0.0,0.0,0.0,1.0);
  return OUT;
}

PixelToFrame multitexturedPS(VertexToPixel IN) 
{
PixelToFrame OUT=(PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;
float4 LightVector = normalize(xLightPosition-IN.Orig_Pos);
float4 Bump=tex2D(RockBumpMapSampler,IN.UV)*IN.TexWeights.z*xRockBumpHeight;
float LightIntensity = dot(LightVector, normalize(mul(IN.Normal+Bump,xRotationMatrix)));
if (xRefraction) if (IN.Pos3D.z>xWaterLevel) {OUT.Depth=1.0;LightIntensity=0.0f; xAmbientLight=float4(0,0,0,0);} 	
if (xReflection) if (IN.Pos3D.z<=xWaterLevel) {OUT.Depth=1.0;LightIntensity=0.0f; xAmbientLight=float4(0,0,0,0);}
OUT.Color = saturate((tex2D(DirtTextureSampler, IN.UV)*IN.TexWeights.x+
       		      tex2D(GrassTextureSampler, IN.UV)*IN.TexWeights.y+
                      tex2D(RockTextureSampler, IN.UV)*IN.TexWeights.z+
                      tex2D(SnowTextureSampler, IN.UV)*IN.TexWeights.w)*LightIntensity+xAmbientLight);
return OUT;       
}

//---------- TEXTURED ---------------

VertexToPixel texturedVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0);
  OUT.Normal=IN.Normal;
	return OUT;
}

PixelToFrame texturedPS(VertexToPixel IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;
float4 LightVector = normalize(xLightPosition - IN.Orig_Pos);
float LightIntensity = dot(LightVector,normalize(mul(IN.Normal,xRotationMatrix)));
if (xRefraction) if (IN.Pos3D.z>xWaterLevel) {OUT.Depth=1.0; LightIntensity=0.0f; xAmbientLight=float4(0,0,0,0);} 	
if (xReflection) if (IN.Pos3D.z<=xWaterLevel) {OUT.Depth=1.0; LightIntensity=0.0f; xAmbientLight=float4(0,0,0,0);} 	
OUT.Color = saturate(tex2D(ColoredTextureSampler, IN.UV)*LightIntensity+xAmbientLight);
return OUT;
}

//----------- SOLID RED ----------
VertexToPixel solidredVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0)+float4(0.03,0.03,0.0,0.0)*xWindSpeed*xTime;
  OUT.Normal=IN.Normal;
  return OUT;
}

PixelToFrame solidredPS(VertexToPixel IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;
OUT.Color = float4(1.0,0,0,0); 	
return OUT;
}

//----------- Depth Buffer ----------
VertexToPixel depthVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0)+float4(0.03,0.03,0.0,0.0)*xWindSpeed*xTime;
  OUT.Normal=IN.Normal;
  return OUT;
}

PixelToFrame depthPS(VertexToPixel IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;
float3 Color=float3(1,1,1)*(IN.Pos2D.z/IN.Pos2D.w);
OUT.Color = float4(Color.xyz,1); 
return OUT;
}

//----------- SOLID GREEN ----------
VertexToPixel solidgreenVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0)+float4(0.03,0.03,0.0,0.0)*xWindSpeed*xTime;
  OUT.Normal=IN.Normal;
  return OUT;
}

PixelToFrame solidgreenPS(VertexToPixel IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;
OUT.Color = float4(0.0,1.0,0,0); 	
return OUT;
}
//----------- TEXTURED (NO LIGHTING) ----------
VertexToPixel nolighttexturedVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0)+float4(0.03,0.03,0.0,0.0)*xWindSpeed*xTime;
  OUT.Normal=IN.Normal;
  return OUT;
}

PixelToFrame nolighttexturedPS(VertexToPixel IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;
OUT.Color = saturate(tex2D(ColoredTextureSampler, IN.UV)+xAmbientLight);
if (xRefraction) if (IN.Pos3D.z>xWaterLevel) {OUT.Depth=1.0; OUT.Color=float4(0,0,0,0);} 	
if (xReflection) if (IN.Pos3D.z<=xWaterLevel) {OUT.Depth=1.0; OUT.Color=float4(0,0,0,0);} 	
return OUT;
}



//---------------- WATER ---------------
WaterVertexToPixel waterVS(WaterBufferToVertex IN)
{
  WaterVertexToPixel OUT = (WaterVertexToPixel)0;
  float4x4 WorldViewProj, RefWorldViewProj;
	  float3 WaveVector = float3(0,0,0.3*sin(0.5*IN.Pos.x+xTime)+0.2*sin(0.52*IN.Pos.y+1.1f*xTime));
  
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  
  RefWorldViewProj = mul (xWorld,xReflectedView);
  RefWorldViewProj = mul (RefWorldViewProj,xProjection);
  
  OUT.Pos=mul(float4(IN.Pos.xyz+WaveVector,1.0), WorldViewProj);
  OUT.RefrPos=mul(float4(IN.Pos.xyz+WaveVector,1.0),WorldViewProj);
  OUT.ReflPos=mul(float4(IN.Pos.xyz+WaveVector,1.0),RefWorldViewProj);
  OUT.Pos3D=float4(IN.Pos.xyz+WaveVector,1.0);
  
  OUT.UV=float4(IN.UV.xy,1.0,1.0);
  OUT.Normal=IN.Normal;
  OUT.BumpPos=IN.UV/xWaveLength+xTime*xWindSpeed*float2(0.0,1.0);
  return OUT;
}


float4 waterPS(WaterVertexToPixel IN) : COLOR 
{
    float4 ReflColor,RefrColor;
    float2 ProjectedTexCoords;
    float4 BumpColor = tex2D(WaterBumpMapSampler, IN.BumpPos);
    float2 Perturbation = xWaveHeight*(BumpColor.rg-0.5f);
    
    ProjectedTexCoords.x = IN.ReflPos.x/IN.ReflPos.w/2.0f + 0.5f;
    ProjectedTexCoords.y = -IN.ReflPos.y/IN.ReflPos.w/2.0f + 0.5f;
    ReflColor=tex2D(ReflectionMapSampler, ProjectedTexCoords+Perturbation);
    
    ProjectedTexCoords.x = IN.RefrPos.x/IN.RefrPos.w/2.0f + 0.5f;
    ProjectedTexCoords.y = -IN.RefrPos.y/IN.RefrPos.w/2.0f + 0.5f;
    RefrColor=tex2D(RefractionMapSampler, ProjectedTexCoords+Perturbation);
    
    float3 EyeVec=normalize(xCameraPosition.xyz-IN.Pos3D);
    float FresnelTerm = dot(EyeVec, normalize(IN.Normal));
    
    
    return saturate(FresnelTerm*RefrColor+(1-FresnelTerm)*ReflColor+xWaterColor);

}


// ------------ TECHNIQUES --------------

//####
technique particle {
	pass p0 {
        AlphaBlendEnable = true;
		BlendOp = ADD;
		SrcBlend = SRCALPHA;
		DestBlend = INVSRCALPHA;

        SrcBlendAlpha = ZERO;
        DestBlendAlpha = ZERO;
        BlendOpAlpha = ADD;
	
		VertexShader = compile vs_3_0 particleVS();
		PixelShader = compile ps_3_0 particlePS();
	}
}

technique cubedepth{
	pass p0 {
		
		VertexShader = compile vs_3_0 cubedepthVS();
		PixelShader = compile ps_3_0 cubedepthPS();
	}
}

technique cubedepthred{
	pass p0 {
		
		VertexShader = compile vs_3_0 cubedepthVS();
		PixelShader = compile ps_3_0 cubedepthPSred();
	}
}

technique cubeshadowmap{
	pass p0 {
		
		VertexShader = compile vs_3_0 cubeshadowmappingVS();
		PixelShader = compile ps_3_0 cubeshadowmappingPS();
	}
}

technique cubeshadowmaptex{
	pass p0 {
		
		VertexShader = compile vs_3_0 cubeshadowmappingtexVS();
		PixelShader = compile ps_3_0 cubeshadowmappingtexPS();
	}
}

//####
technique depth{
	pass p0 {
		
		VertexShader = compile vs_3_0 depthVS();
		PixelShader = compile ps_3_0 depthPS();
	}
}

technique nolighttextured {
	pass p0 {
		VertexShader = compile vs_3_0 nolighttexturedVS();
		PixelShader = compile ps_3_0 nolighttexturedPS();
	}
}

technique textured {
	pass p0 {
		VertexShader = compile vs_3_0 texturedVS();
		PixelShader = compile ps_3_0 texturedPS();
	}
}


technique multitextured {
	pass p0 {
		VertexShader = compile vs_3_0 multitexturedVS();
		PixelShader = compile ps_3_0 multitexturedPS();
	}
}

technique water {
	pass p0 {
		VertexShader = compile vs_3_0 waterVS();
		PixelShader = compile ps_3_0 waterPS();
	}
}


technique solidred {
	pass p0 {
		VertexShader = compile vs_3_0 solidredVS();
		PixelShader = compile ps_3_0 solidredPS();
	}
}

technique solidgreen {
	pass p0 {
		VertexShader = compile vs_3_0 solidgreenVS();
		PixelShader = compile ps_3_0 solidgreenPS();
	}
}
